defmodule IocpMonitor.Sender do
  @moduledoc """
  TCP包发送模块
  """

  use IocpMonitor.Types

  @packet_start [0x68, 0x16]

  require Bitwise
  import IocpMonitor.LittleEndian

  @doc """
  发送获取设备地址的TCP包
  """
  @spec device_address!(tcp_client()) :: :ok
  def device_address!(client) do
    packet = pack([
      0x04,
      0xFF,
      0xFF
    ])
    :ok = :gen_tcp.send(client, packet)
  end

  @doc """
  发送对时的TCP包
  """
  @spec adjust_time!(tcp_client(), integer()) :: :ok
  def adjust_time!(client, device_address) do
    %DateTime{
      year: year,
      month: month,
      day: day,
      hour: hour,
      minute: minute,
      second: second
    } = Timex.local()

    packet = pack([
      0x02,
      to_bytes(device_address),
      second,
      minute,
      hour,
      day,
      month,
      rem(year, 100)
    ])
    :ok = :gen_tcp.send(client, packet)
  end

  @doc """
  发送获取实时数据的TCP包
  """
  @spec realtime_data!(tcp_client(), integer()) :: :ok
  def realtime_data!(client, device_address) do
    packet = pack([
      0x01,
      to_bytes(device_address)
    ])
    :ok = :gen_tcp.send(client, packet)
  end

  defp pack(data) do
    data = List.flatten(data)
    data_length = length(data) + 2  # 1位控制码，1位校验码
    data = [@packet_start, to_bytes(data_length), 0, data] |> List.flatten()
    checksum = data |> Enum.sum() |> Bitwise.&&&(0xFF)
    [data, checksum]
  end
end
